package com.example.demo.service.impl;

import com.example.demo.dto.NewTaskDTO;
import com.example.demo.dto.DataSourceTaskStatsDTO;
import com.example.demo.dto.TaskDetailDTO;
import com.example.demo.dto.DataSourceSearchConfigDTO;
import com.example.demo.dto.QueryResultDTO;
import com.example.demo.entity.DataSource;
import com.example.demo.entity.NewTask;
import com.example.demo.entity.TaskType;
import com.example.demo.exception.BusinessException;
import com.example.demo.mapper.NewTaskMapper;
import com.example.demo.mapper.DataSourceMapper;
import com.example.demo.mapper.TaskTypeMapper;
import com.example.demo.request.SearchNewTaskRequest;
import com.example.demo.request.CreateNewTaskRequest;
import com.example.demo.request.ExecuteQueryRequest;
import com.example.demo.service.NewTaskService;
import com.example.demo.service.DataSourceService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.security.MessageDigest;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Service
public class NewTaskServiceImpl implements NewTaskService {

//    private static final logger log = loggerFactory.getlogger(NewTaskServiceImpl.class);

    @Autowired
    private NewTaskMapper newTaskMapper;

    @Autowired
    private DataSourceMapper dataSourceMapper;

    @Autowired
    private DataSourceService dataSourceService;

    @Autowired
    private TaskTypeMapper taskTypeMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public List<NewTaskDTO> getNewTasks(int page, int size, Long dataSourceId, Integer isAssigned) {
        int offset = page * size;
        List<NewTask> newTasks = newTaskMapper.selectPage(offset, size, dataSourceId, isAssigned);
        return newTasks.stream()
                .map(NewTaskDTO::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    public long countNewTasks(Long dataSourceId, Integer isAssigned) {
        return newTaskMapper.count(dataSourceId, isAssigned);
    }

    @Override
    public NewTaskDTO getNewTaskById(Long id) {
        NewTask newTask = newTaskMapper.selectById(id);
        if (newTask == null) {
            throw new BusinessException("任务不存在，ID：" + id);
        }
        return NewTaskDTO.fromEntity(newTask);
    }

    @Override
    public NewTaskDTO getNewTaskByBizUniqueId(String bizUniqueId) {
        NewTask newTask = newTaskMapper.selectByBizUniqueId(bizUniqueId);
        if (newTask == null) {
            throw new BusinessException("任务不存在，业务唯一ID：" + bizUniqueId);
        }
        return NewTaskDTO.fromEntity(newTask);
    }

    @Override
    @Transactional
    public NewTaskDTO createNewTask(CreateNewTaskRequest request) {
        // 检查任务是否已存在（使用dataSourceId和bizUniqueId联合判断）
        NewTask existingTask = newTaskMapper.selectByDataSourceIdAndBizUniqueId(request.getDataSourceId(),
                request.getBizUniqueId());
        if (existingTask != null) {
            throw new BusinessException(
                    "任务已存在，数据源ID：" + request.getDataSourceId() + "，业务唯一ID：" + request.getBizUniqueId());
        }

        NewTask newTask = new NewTask();
        newTask.setBizUniqueId(request.getBizUniqueId());
        newTask.setDataSourceId(request.getDataSourceId());
        newTask.setRawData(request.getRawData());
        newTask.setIsAssigned(0); // 默认未分配
        newTask.setIsComplete(0); // 默认未完成
        newTask.setCreatedAt(LocalDateTime.now());
        newTask.setUpdatedAt(LocalDateTime.now());

        int result = newTaskMapper.insert(newTask);
        if (result == 0) {
            throw new BusinessException("任务创建失败");
        }
        return NewTaskDTO.fromEntity(newTask);
    }

    @Override
    @Transactional
    public NewTaskDTO updateNewTask(Long id, CreateNewTaskRequest request) {
        NewTask existingTask = newTaskMapper.selectById(id);
        if (existingTask == null) {
            throw new BusinessException("任务不存在，无法更新");
        }

        // 检查业务唯一ID是否已被其他任务使用
        if (!existingTask.getBizUniqueId().equals(request.getBizUniqueId())) {
            NewTask otherTask = newTaskMapper.selectByBizUniqueId(request.getBizUniqueId());
            if (otherTask != null && !otherTask.getId().equals(id)) {
                throw new BusinessException("业务唯一ID已被使用：" + request.getBizUniqueId());
            }
        }

        existingTask.setBizUniqueId(request.getBizUniqueId());
        existingTask.setDataSourceId(request.getDataSourceId());
        existingTask.setRawData(request.getRawData());
        existingTask.setUpdatedAt(LocalDateTime.now());

        int result = newTaskMapper.updateById(existingTask);
        if (result == 0) {
            throw new BusinessException("任务更新失败");
        }
        return NewTaskDTO.fromEntity(existingTask);
    }

    @Override
    @Transactional
    public void deleteNewTask(Long id) {
        NewTask newTask = newTaskMapper.selectById(id);
        if (newTask == null) {
            throw new BusinessException("任务不存在，无法删除");
        }
        int result = newTaskMapper.deleteById(id);
        if (result == 0) {
            throw new BusinessException("任务删除失败");
        }
    }

    @Override
    @Transactional
    public void updateNewTaskAssignedStatus(Long id, Integer isAssigned) {
        NewTask existingTask = newTaskMapper.selectById(id);
        if (existingTask == null) {
            throw new BusinessException("任务不存在，无法更新分配状态");
        }

        existingTask.setIsAssigned(isAssigned);
        existingTask.setUpdatedAt(LocalDateTime.now());

        int result = newTaskMapper.updateById(existingTask);
        if (result == 0) {
            throw new BusinessException("任务分配状态更新失败");
        }
    }

    @Override
    @Transactional
    public void updateNewTaskCompleteStatus(Long id, Integer isComplete) {
        NewTask existingTask = newTaskMapper.selectById(id);
        if (existingTask == null) {
            throw new BusinessException("任务不存在，无法更新完成状态");
        }

        existingTask.setIsComplete(isComplete);
        existingTask.setUpdatedAt(LocalDateTime.now());

        int result = newTaskMapper.updateById(existingTask);
        if (result == 0) {
            throw new BusinessException("任务完成状态更新失败");
        }
    }

    @Override
    @Transactional
    public int syncTasksFromDataSource(Long dataSourceId) {
        // 1. 获取数据源配置
        DataSource dataSource = dataSourceMapper.selectById(dataSourceId);
        if (dataSource == null) {
            throw new BusinessException("数据源不存在，ID：" + dataSourceId);
        }

        // 2. 检查数据源是否启用
        if (dataSource.getStatus() != 1) {
            throw new BusinessException("数据源未启用，无法同步任务");
        }

        // 3. 检查查询SQL是否配置
        if (dataSource.getQuerySql() == null || dataSource.getQuerySql().trim().isEmpty()) {
            throw new BusinessException("数据源未配置查询SQL，无法同步任务");
        }

        try {
            // 4. 执行查询获取数据
            ExecuteQueryRequest queryRequest = new ExecuteQueryRequest();
            queryRequest.setSql(dataSource.getQuerySql());
            queryRequest.setLimit(10000); // 限制最大返回行数
            queryRequest.setTimeoutSeconds(60); // 设置查询超时时间

            QueryResultDTO queryResult = dataSourceService.executeQuery(dataSourceId, queryRequest);
            List<Map<String, Object>> rows = queryResult.getRows();

            if (rows == null || rows.isEmpty()) {
                //log.info("数据源查询结果为空，数据源ID：{}", dataSourceId);
                return 0;
            }

            // 5. 获取并更新下拉字段配置
            List<DataSourceSearchConfigDTO.DropdownFieldConfig> dropdownFieldConfigs = 
                updateDropdownFieldOptionsFromDataSource(dataSource, rows);

            // 6. 处理查询结果，生成任务列表
            List<NewTask> tasksToSync = new ArrayList<>();
            for (Map<String, Object> row : rows) {
                NewTask task = new NewTask();
                task.setDataSourceId(dataSourceId);

                // 生成bizUniqueId
                String bizUniqueId = generateBizUniqueId(row, dataSource);
                task.setBizUniqueId(bizUniqueId);

                // 填充下拉字段的值
                populateDropdownFieldValues(row, dropdownFieldConfigs);

                // 将行数据转换为JSON字符串作为rawData
                String rawData = objectMapper.writeValueAsString(row);
                task.setRawData(rawData);

                // 默认未分配
                task.setIsAssigned(0);
                // 默认未完成
                task.setIsComplete(0);
                task.setCreatedAt(LocalDateTime.now());
                task.setUpdatedAt(LocalDateTime.now());

                tasksToSync.add(task);
            }

            // 7. 批量插入任务数据
            int totalInserted = insertBatchTasks(tasksToSync);

            //log.info("从数据源同步任务成功，数据源ID：{}，同步任务数量：{}", dataSourceId, totalInserted);
            return totalInserted;
        } catch (Exception e) {
            //log.error("从数据源同步任务失败，数据源ID：{}，错误：{}", dataSourceId, e.getMessage(), e);
            throw new BusinessException("任务同步失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public int insertBatchTasks(List<NewTask> tasks) {
        if (tasks == null || tasks.isEmpty()) {
            return 0;
        }

        // 过滤掉已存在的任务（使用dataSourceId和bizUniqueId联合判断）
        List<NewTask> tasksToInsert = new ArrayList<>();
        for (NewTask task : tasks) {
            NewTask existingTask = newTaskMapper.selectByDataSourceIdAndBizUniqueId(task.getDataSourceId(),
                    task.getBizUniqueId());
            if (existingTask == null) {
                // 设置默认值
                if (task.getIsComplete() == null) {
                    task.setIsComplete(0); // 默认未完成
                }
                tasksToInsert.add(task);
            }
        }

        if (tasksToInsert.isEmpty()) {
            return 0;
        }

        // 分批处理，每批最多1000条
        int batchSize = 1000;
        int totalInserted = 0;

        for (int i = 0; i < tasksToInsert.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, tasksToInsert.size());
            List<NewTask> batch = tasksToInsert.subList(i, endIndex);

            int inserted = newTaskMapper.insertBatch(batch);
            totalInserted += inserted;
        }

        return totalInserted;
    }

    /**
     * 根据数据源配置的idFields生成业务唯一ID
     */
    private String generateBizUniqueId(Map<String, Object> rowData, DataSource dataSource) {
        try {
            // 创建一个字符串，包含所有字段的值
            StringBuilder fieldValues = new StringBuilder();

            // 如果配置了idFields，则只使用这些字段
            if (dataSource.getIdFields() != null && !dataSource.getIdFields().trim().isEmpty()) {
                // 解析idFields JSON数组
                List<String> idFields = objectMapper.readValue(dataSource.getIdFields(), List.class);

                // 按字段名排序，确保生成的ID一致
                Collections.sort(idFields);

                for (String field : idFields) {
                    Object value = rowData.get(field);
                    fieldValues.append(field).append(":").append(value != null ? value.toString() : "null")
                            .append("; ");
                }
            } else {
                // 如果没有配置idFields，使用所有字段
                // 按字段名排序，确保生成的ID一致
                List<String> sortedKeys = new ArrayList<>(rowData.keySet());
                Collections.sort(sortedKeys);

                for (String key : sortedKeys) {
                    Object value = rowData.get(key);
                    fieldValues.append(key).append(":").append(value != null ? value.toString() : "null").append("; ");
                }
            }

            // 添加数据源ID作为前缀，确保不同数据源的任务ID唯一
            fieldValues.append("dataSourceId:").append(dataSource.getId());

            // 使用MD5算法生成唯一标识
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashBytes = md.digest(fieldValues.toString().getBytes("UTF-8"));

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1)
                    hexString.append('0');
                hexString.append(hex);
            }

            return hexString.toString();
        } catch (Exception e) {
            //log.error("生成业务唯一ID失败：{}", e.getMessage(), e);
            // 如果生成失败，使用UUID作为后备方案
            return UUID.randomUUID().toString().replace("-", "");
        }
    }

    /**
     * 填充下拉字段的值
     * 确保下拉字段的值在预定义的选项列表中，如果不在则设置为null
     */
    private void populateDropdownFieldValues(Map<String, Object> rowData, 
                                           List<DataSourceSearchConfigDTO.DropdownFieldConfig> dropdownFieldConfigs) {
        if (dropdownFieldConfigs == null || dropdownFieldConfigs.isEmpty()) {
            return;
        }
        
        int modifiedCount = 0;
        for (DataSourceSearchConfigDTO.DropdownFieldConfig config : dropdownFieldConfigs) {
            String fieldName = config.getName();
            List<String> options = config.getOptions();

            // 如果字段在行数据中存在
            if (rowData.containsKey(fieldName)) {
                Object value = rowData.get(fieldName);
                
                // 如果值不为空且选项列表不为空，则验证值是否在选项列表中
                if (value != null && options != null && !options.isEmpty()) {
                    String stringValue = value.toString();
                    // 如果值不在选项列表中，则设置为null
                    if (!options.contains(stringValue)) {
                        rowData.put(fieldName, null);
                        modifiedCount++;
                    }
                }
            }
        }
        
        // 只在有修改时记录日志
        if (modifiedCount > 0) {
            //log.info("填充下拉字段值完成，共修改 {} 个字段", modifiedCount);
        }
    }

    @Override
    public List<DataSourceTaskStatsDTO> getAllDataSourceTaskStats() {
        //log.info("开始获取所有数据源任务统计信息");
        
        // 1. 先查询所有任务信息
        List<NewTask> allTasks = newTaskMapper.selectAll();
        //log.info("查询到所有任务数量: {}", allTasks.size());
        
        // 如果没有任务信息，直接返回空列表
        if (allTasks.isEmpty()) {
            //log.info("没有查询到任务信息，统计信息不进行返回");
            return new ArrayList<>();
        }
        
        // 2. 按数据源ID分组统计
        Map<Long, List<NewTask>> tasksByDataSource = allTasks.stream()
                .collect(Collectors.groupingBy(NewTask::getDataSourceId));
        //log.info("按数据源分组后，共有 {} 个数据源", tasksByDataSource.size());
        
        // 3. 为每个数据源构建统计信息
        List<DataSourceTaskStatsDTO> statsList = new ArrayList<>();
        for (Map.Entry<Long, List<NewTask>> entry : tasksByDataSource.entrySet()) {
            Long dataSourceId = entry.getKey();
            List<NewTask> tasks = entry.getValue();
            //log.info("处理数据源ID: {}, 任务数量: {}", dataSourceId, tasks.size());
            
            // 查询数据源信息
            DataSource dataSource = dataSourceMapper.selectById(dataSourceId);
            String dataSourceName = dataSource != null ? dataSource.getName() : "未知数据源";
            //log.info("数据源ID: {} 对应的数据源名称: {}", dataSourceId, dataSourceName);
            
            // 统计任务数量
            long totalTasks = tasks.size();
            long assignedTasks = tasks.stream().mapToLong(task -> task.getIsAssigned() == 1 ? 1 : 0).sum();
            long unassignedTasks = totalTasks - assignedTasks;
            //log.info("数据源ID: {} 任务统计 - 总数: {}, 已分配: {}, 未分配: {}", 
//                    dataSourceId, totalTasks, assignedTasks, unassignedTasks);
            
            // 查询任务类型信息（从第一个任务获取，假设同一数据源的任务类型相同）
            Long taskTypeId = null;
            String taskTypeName = null;
            if (!tasks.isEmpty()) {
                // 通过数据源ID查询任务类型
                List<TaskType> taskTypes = taskTypeMapper.selectByDataSourceId(dataSourceId);
                //log.info("数据源ID: {} 查询到任务类型数量: {}", dataSourceId, taskTypes != null ? taskTypes.size() : 0);
                if (taskTypes != null && !taskTypes.isEmpty()) {
                    TaskType taskType = taskTypes.get(0); // 取第一个任务类型
                    taskTypeId = taskType.getTaskTypeId();
                    taskTypeName = taskType.getTaskName();
                    //log.info("数据源ID: {} 使用任务类型 - ID: {}, 名称: {}", dataSourceId, taskTypeId, taskTypeName);
                } else {
                    //log.warn("数据源ID: {} 没有查询到任务类型信息，跳过统计信息构建", dataSourceId);
                    continue; // 跳过没有任务类型的数据源
                }
            }
            
            DataSourceTaskStatsDTO statsDTO = new DataSourceTaskStatsDTO(
                    dataSourceId, dataSourceName, taskTypeId, taskTypeName, totalTasks, assignedTasks, unassignedTasks);
            statsList.add(statsDTO);
            //log.info("数据源ID: {} 统计信息构建完成", dataSourceId);
        }
        
        //log.info("所有数据源任务统计信息获取完成，返回 {} 条记录，在没有查询到任务信息的时候，统计信息也不进行返回", statsList.size());
        return statsList;
    }

    @Override
    public DataSourceTaskStatsDTO getDataSourceTaskStatsById(Long dataSourceId) {
        //log.info("开始获取数据源ID: {} 的任务统计信息", dataSourceId);
        
        // 1. 先查询指定数据源的任务信息
        List<NewTask> tasks = newTaskMapper.selectPage(0, Integer.MAX_VALUE, dataSourceId, null);
        //log.info("数据源ID: {} 查询到任务数量: {}", dataSourceId, tasks.size());
        
        if (tasks.isEmpty()) {
            //log.warn("数据源ID: {} 没有找到任何任务，统计信息不进行返回", dataSourceId);
            // 没有任务信息时，返回null
            return null;
        }
        
        // 2. 查询数据源信息
        DataSource dataSource = dataSourceMapper.selectById(dataSourceId);
        String dataSourceName = dataSource != null ? dataSource.getName() : "未知数据源";
        //log.info("数据源ID: {} 对应的数据源名称: {}", dataSourceId, dataSourceName);
        
        // 3. 统计任务数量
        long totalTasks = tasks.size();
        long assignedTasks = tasks.stream().mapToLong(task -> task.getIsAssigned() == 1 ? 1 : 0).sum();
        long unassignedTasks = totalTasks - assignedTasks;
        //log.info("数据源ID: {} 任务统计 - 总数: {}, 已分配: {}, 未分配: {}", 
//                dataSourceId, totalTasks, assignedTasks, unassignedTasks);
        
        // 4. 查询任务类型信息
        Long taskTypeId = null;
        String taskTypeName = null;
        List<TaskType> taskTypes = taskTypeMapper.selectByDataSourceId(dataSourceId);
        //log.info("数据源ID: {} 查询到任务类型数量: {}", dataSourceId, taskTypes != null ? taskTypes.size() : 0);
        if (taskTypes != null && !taskTypes.isEmpty()) {
            TaskType taskType = taskTypes.get(0); // 取第一个任务类型
            taskTypeId = taskType.getTaskTypeId();
            taskTypeName = taskType.getTaskName();
            //log.info("数据源ID: {} 使用任务类型 - ID: {}, 名称: {}", dataSourceId, taskTypeId, taskTypeName);
        } else {
            //log.warn("数据源ID: {} 没有找到对应的任务类型，统计信息不进行返回", dataSourceId);
            return null; // 没有任务类型信息时，返回null
        }
        
        DataSourceTaskStatsDTO result = new DataSourceTaskStatsDTO(dataSourceId, dataSourceName, taskTypeId, taskTypeName, totalTasks, assignedTasks, unassignedTasks);
        //log.info("数据源ID: {} 统计信息获取完成，返回结果: {}", dataSourceId, result);
        return result;
    }



    @Override
    public TaskDetailDTO getTaskDetail(Long taskId) {
        // 1. 获取任务基本信息
        NewTask task = newTaskMapper.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在，ID：" + taskId);
        }

        // 2. 获取数据源信息
        DataSource dataSource = dataSourceMapper.selectById(task.getDataSourceId());
        if (dataSource == null) {
            throw new BusinessException("数据源不存在，ID：" + task.getDataSourceId());
        }

        return buildTaskDetailDTO(task, dataSource);
    }

    @Override
    public List<TaskDetailDTO> getTaskDetails(int page, int size, Long dataSourceId, Integer isAssigned) {
        //log.info("调用getTaskDetails方法，数据源ID: {}, page: {}, size: {}, isAssigned: {}", dataSourceId, page, size,
//                isAssigned);

        // 1. 获取数据源信息
        DataSource dataSource = dataSourceMapper.selectById(dataSourceId);
        if (dataSource == null) {
            throw new BusinessException("数据源不存在，ID：" + dataSourceId);
        }

        //log.info("数据源信息: name={}, displayFields={}, extraFields={}",
//                dataSource.getName(), dataSource.getDisplayFields(), dataSource.getExtraFields());

        // 2. 分页查询任务列表
        int offset = page * size;
        List<NewTask> newTasks = newTaskMapper.selectPage(offset, size, dataSourceId, isAssigned);

        //log.info("查询到任务数量: {}", newTasks.size());

        // 3. 转换为TaskDetailDTO并应用displayFields过滤
        List<TaskDetailDTO> result = newTasks.stream()
                .map(task -> buildTaskDetailDTO(task, dataSource))
                .collect(Collectors.toList());

        //log.info("返回TaskDetailDTO数量: {}, 第一个对象的displayData字段数: {}",
//                result.size(), result.isEmpty() ? 0 : result.get(0).getDisplayData().size());

        return result;
    }

    /**
     * 构建 TaskDetailDTO 对象，应用 displayFields 过滤逻辑
     */
    private TaskDetailDTO buildTaskDetailDTO(NewTask task, DataSource dataSource) {
        //log.debug("构建TaskDetailDTO, taskId: {}, dataSourceName: {}", task.getId(), dataSource.getName());

        // 3. 构建返回对象
        TaskDetailDTO result = new TaskDetailDTO();

        // 设置基本信息
        result.setId(task.getId());
        result.setBizUniqueId(task.getBizUniqueId());
        result.setDataSourceId(task.getDataSourceId());
        result.setDataSourceName(dataSource.getName());
        result.setIsAssigned(task.getIsAssigned());
        result.setIsAssignedText(task.getIsAssigned() == 1 ? "已分配" : "未分配");
        result.setCreatedAt(task.getCreatedAt());
        result.setUpdatedAt(task.getUpdatedAt());

        try {
            // 4. 解析rawData
            Map<String, Object> rawDataMap = new HashMap<>();
            if (task.getRawData() != null && !task.getRawData().trim().isEmpty()) {
                rawDataMap = objectMapper.readValue(task.getRawData(), Map.class);
            }
            result.setTaskData(rawDataMap);
            //log.debug("解析rawData完成，字段数: {}", rawDataMap.size());

            // 5. 解析extraFields
            Map<String, Object> extraDataMap = new HashMap<>();
            if (dataSource.getExtraFields() != null && !dataSource.getExtraFields().trim().isEmpty()) {
                extraDataMap = objectMapper.readValue(dataSource.getExtraFields(), Map.class);
            }
            result.setExtraData(extraDataMap);
            //log.debug("解析extraFields完成，字段数: {}", extraDataMap.size());

            // 6. 合并数据
            Map<String, Object> combinedData = new HashMap<>();
            combinedData.putAll(rawDataMap);
            combinedData.putAll(extraDataMap); // extraFields会覆盖rawData中的同名字段
            //log.debug("合并数据完成，字段数: {}", combinedData.size());

            // 7. 按displayFields过滤
            Map<String, Object> displayData = new HashMap<>();
            if (dataSource.getDisplayFields() != null && !dataSource.getDisplayFields().trim().isEmpty()) {
                //log.info("应用displayFields过滤: {}", dataSource.getDisplayFields());
                List<String> displayFieldsList = objectMapper.readValue(dataSource.getDisplayFields(), List.class);
                //log.info("解析后的displayFields列表: {}", displayFieldsList);
                //log.info("combinedData可用字段: {}", combinedData.keySet());

                for (String field : displayFieldsList) {
                    if (combinedData.containsKey(field)) {
                        displayData.put(field, combinedData.get(field));
                        //log.debug("添加字段到displayData: {} = {}", field, combinedData.get(field));
                    } else {
                        //log.warn("displayFields中的字段在combinedData中不存在: {}", field);
                    }
                }
                //log.info("过滤后的displayData字段数: {}, 内容: {}", displayData.size(), displayData.keySet());
            } else {
                // 如果没有配置displayFields，则返回所有合并后的数据
                //log.info("没有配置displayFields，返回所有数据，字段数: {}", combinedData.size());
                displayData = combinedData;
            }
            result.setDisplayData(displayData);

            //log.info("最终TaskDetailDTO - id: {}, displayData字段数: {}", result.getId(), result.getDisplayData().size());

            return result;
        } catch (Exception e) {
            //log.error("解析任务详情数据失败，任务ID：{}，错误：{}", task.getId(), e.getMessage(), e);
            throw new BusinessException("解析任务详情数据失败：" + e.getMessage());
        }
    }

    @Override
    public DataSourceSearchConfigDTO getDataSourceSearchConfig(Long dataSourceId) {
        // 获取数据源信息
        DataSource dataSource = dataSourceMapper.selectById(dataSourceId);
        if (dataSource == null) {
            throw new BusinessException("数据源不存在，ID：" + dataSourceId);
        }

        DataSourceSearchConfigDTO config = new DataSourceSearchConfigDTO();
        config.setDataSourceId(dataSourceId);
        config.setDataSourceName(dataSource.getName());

        // 解析dropdownFields
        if (dataSource.getDropdownFields() != null && !dataSource.getDropdownFields().trim().isEmpty()) {
            try {
                List<DataSourceSearchConfigDTO.DropdownFieldConfig> dropdownConfigs = objectMapper.readValue(
                        dataSource.getDropdownFields(),
                        new TypeReference<List<DataSourceSearchConfigDTO.DropdownFieldConfig>>() {
                        });
                config.setDropdownFields(dropdownConfigs);
            } catch (Exception e) {
                //log.error("解析下拉字段配置失败: {}", e.getMessage());
                config.setDropdownFields(new ArrayList<>());
            }
        } else {
            config.setDropdownFields(new ArrayList<>());
        }

        // 解析searchableFields
        if (dataSource.getSearchableFields() != null && !dataSource.getSearchableFields().trim().isEmpty()) {
            try {
                List<DataSourceSearchConfigDTO.SearchableFieldConfig> searchableConfigs = objectMapper.readValue(
                        dataSource.getSearchableFields(),
                        new TypeReference<List<DataSourceSearchConfigDTO.SearchableFieldConfig>>() {
                        });
                config.setSearchableFields(searchableConfigs);
            } catch (Exception e) {
                //log.error("解析搜索字段配置失败: {}", e.getMessage());
                config.setSearchableFields(new ArrayList<>());
            }
        } else {
            config.setSearchableFields(new ArrayList<>());
        }

        return config;
    }

    @Override
    public List<TaskDetailDTO> searchNewTasks(SearchNewTaskRequest request) {
        //log.info("开始执行任务搜索，请求参数: {}", request);
        
        // 创建专门的日志记录器，用于记录到文件
        String logFileName = "logs/search_tasks.log";
        writeSearchlog(logFileName, "开始执行任务搜索，请求参数: " + request);
        
        // 参数验证
        if (request.getDataSourceId() == null) {
            String errorMsg = "数据源ID不能为空";
            //log.warn(errorMsg);
            writeSearchlog(logFileName, "错误: " + errorMsg);
            throw new BusinessException(errorMsg);
        }

        try {
            // 获取数据源搜索配置，验证搜索字段
            //log.info("获取数据源ID {} 的搜索配置", request.getDataSourceId());
            writeSearchlog(logFileName, "获取数据源ID " + request.getDataSourceId() + " 的搜索配置");
            
            DataSourceSearchConfigDTO config = getDataSourceSearchConfig(request.getDataSourceId());
            //log.debug("数据源搜索配置: dropdownFields={}, searchableFields={}", 
//                     config.getDropdownFields(), config.getSearchableFields());
            writeSearchlog(logFileName, "数据源搜索配置获取成功");
            
            Map<String, Object> validatedParams = validateAndFilterSearchParams(request.getSearchParams(), config);
            //log.info("验证后的搜索参数: {}", validatedParams);
            writeSearchlog(logFileName, "验证后的搜索参数: " + validatedParams);

            int offset = request.getPage() * request.getSize();
            //log.info("执行任务搜索，offset={}, size={}, dataSourceId={}, isAssigned={}", 
//                    offset, request.getSize(), request.getDataSourceId(), request.getIsAssigned());
            writeSearchlog(logFileName, String.format("执行任务搜索，offset=%d, size=%d, dataSourceId=%d, isAssigned=%s", 
                    offset, request.getSize(), request.getDataSourceId(), request.getIsAssigned()));
            
            List<NewTask> tasks = newTaskMapper.searchTasks(offset, request.getSize(),
                    request.getDataSourceId(), request.getIsAssigned(), validatedParams);
            
            //log.info("搜索完成，找到 {} 条任务记录", tasks.size());
            writeSearchlog(logFileName, "搜索完成，找到 " + tasks.size() + " 条任务记录");
            
            // 获取数据源信息用于构建TaskDetailDTO
            DataSource dataSource = dataSourceMapper.selectById(request.getDataSourceId());
            if (dataSource == null) {
                String errorMsg = "数据源不存在，ID：" + request.getDataSourceId();
                //log.error(errorMsg);
                writeSearchlog(logFileName, "错误: " + errorMsg);
                throw new BusinessException(errorMsg);
            }
            
            // 转换为TaskDetailDTO并应用displayFields过滤
            List<TaskDetailDTO> result = tasks.stream()
                    .map(task -> buildTaskDetailDTO(task, dataSource))
                    .collect(Collectors.toList());
                    
            //log.info("转换完成，返回 {} 条任务详情记录", result.size());
            writeSearchlog(logFileName, "转换完成，返回 " + result.size() + " 条任务详情记录");
            return result;
        } catch (Exception e) {
            String errorMsg = "任务搜索失败：" + e.getMessage();
            //log.error("任务搜索失败，请求参数: {}, 错误信息: {}", request, e.getMessage(), e);
            writeSearchlog(logFileName, "错误: " + errorMsg + ", 详细信息: " + e.getMessage());
            throw new BusinessException(errorMsg);
        }
    }

    @Override
    public long countSearchNewTasks(SearchNewTaskRequest request) {
        //log.info("开始统计搜索结果数量，请求参数: {}", request);
        
        // 创建专门的日志记录器，用于记录到文件
        String logFileName = "logs/search_tasks_count.log";
        writeSearchlog(logFileName, "开始统计搜索结果数量，请求参数: " + request);
        
        // 参数验证
        if (request.getDataSourceId() == null) {
            String errorMsg = "数据源ID不能为空";
            //log.warn(errorMsg);
            writeSearchlog(logFileName, "错误: " + errorMsg);
            throw new BusinessException(errorMsg);
        }

        try {
            // 获取数据源搜索配置，验证搜索字段
            //log.info("获取数据源ID {} 的搜索配置用于统计", request.getDataSourceId());
            writeSearchlog(logFileName, "获取数据源ID " + request.getDataSourceId() + " 的搜索配置用于统计");
            
            DataSourceSearchConfigDTO config = getDataSourceSearchConfig(request.getDataSourceId());
            //log.debug("数据源搜索配置: dropdownFields={}, searchableFields={}", 
//                     config.getDropdownFields(), config.getSearchableFields());
            writeSearchlog(logFileName, "数据源搜索配置获取成功");
            
            Map<String, Object> validatedParams = validateAndFilterSearchParams(request.getSearchParams(), config);
            //log.info("验证后的搜索参数: {}", validatedParams);
            writeSearchlog(logFileName, "验证后的搜索参数: " + validatedParams);

            //log.info("执行搜索结果统计，dataSourceId={}, isAssigned={}", 
//                    request.getDataSourceId(), request.getIsAssigned());
            writeSearchlog(logFileName, String.format("执行搜索结果统计，dataSourceId=%d, isAssigned=%s", 
                    request.getDataSourceId(), request.getIsAssigned()));
            
            long count = newTaskMapper.countSearchTasks(request.getDataSourceId(), request.getIsAssigned(), validatedParams);
            
            //log.info("统计完成，符合条件的任务数量: {}", count);
            writeSearchlog(logFileName, "统计完成，符合条件的任务数量: " + count);
            return count;
        } catch (Exception e) {
            String errorMsg = "统计搜索结果数量失败：" + e.getMessage();
            //log.error("统计搜索结果数量失败，请求参数: {}, 错误信息: {}", request, e.getMessage(), e);
            writeSearchlog(logFileName, "错误: " + errorMsg + ", 详细信息: " + e.getMessage());
            throw new BusinessException(errorMsg);
        }
    }

    /**
     * 验证和过滤搜索参数，确保只使用配置中允许的搜索字段
     */
    private Map<String, Object> validateAndFilterSearchParams(Map<String, Object> searchParams,
            DataSourceSearchConfigDTO config) {
        //log.debug("开始验证和过滤搜索参数，原始参数: {}", searchParams);
        
        if (searchParams == null || searchParams.isEmpty()) {
            //log.debug("搜索参数为空，返回空的验证参数");
            return new HashMap<>();
        }

        // 获取所有允许的搜索字段名
        Set<String> allowedFields = new HashSet<>();
        if (config.getSearchableFields() != null) {
            allowedFields.addAll(config.getSearchableFields().stream()
                    .map(DataSourceSearchConfigDTO.SearchableFieldConfig::getName)
                    .collect(Collectors.toSet()));
            //log.debug("可搜索字段: {}", config.getSearchableFields().stream()
//                    .map(DataSourceSearchConfigDTO.SearchableFieldConfig::getName)
//                    .collect(Collectors.toList()));
        }
        if (config.getDropdownFields() != null) {
            allowedFields.addAll(config.getDropdownFields().stream()
                    .map(DataSourceSearchConfigDTO.DropdownFieldConfig::getName)
                    .collect(Collectors.toSet()));
//            //log.debug("下拉字段: {}", config.getDropdownFields().stream()
//                    .map(DataSourceSearchConfigDTO.DropdownFieldConfig::getName)
//                    .collect(Collectors.toList()));
        }

        //log.debug("所有允许的搜索字段: {}", allowedFields);

        // 过滤出允许的搜索字段
        Map<String, Object> validatedParams = new HashMap<>();
        for (Map.Entry<String, Object> entry : searchParams.entrySet()) {
            String fieldName = entry.getKey();
            Object value = entry.getValue();

            // 检查字段是否在允许列表中
            if (allowedFields.contains(fieldName) && value != null && !value.toString().trim().isEmpty()) {
                validatedParams.put(fieldName, value);
                //log.debug("保留搜索字段: {} = {}", fieldName, value);
            } else {
                //log.warn("搜索字段不在配置中或值为空，已忽略：{} = {}", fieldName, value);
            }
        }

        //log.debug("验证后的搜索参数: {}", validatedParams);
        return validatedParams;
    }

    /**
     * 从数据源获取下拉字段选项值并更新数据源配置
     */
    public List<DataSourceSearchConfigDTO.DropdownFieldConfig> updateDropdownFieldOptionsFromDataSource(
            DataSource dataSource, List<Map<String, Object>> rows) {
        List<DataSourceSearchConfigDTO.DropdownFieldConfig> dropdownFieldConfigs = new ArrayList<>();
        
        // 1. 解析现有的下拉字段配置
        if (dataSource.getDropdownFields() != null && !dataSource.getDropdownFields().trim().isEmpty()) {
            try {
                dropdownFieldConfigs = objectMapper.readValue(
                        dataSource.getDropdownFields(),
                        new TypeReference<List<DataSourceSearchConfigDTO.DropdownFieldConfig>>() {
                        });
            } catch (Exception e) {
                //log.warn("解析下拉字段配置失败: {}", e.getMessage());
                return dropdownFieldConfigs; // 返回空列表
            }
        } else {
            return dropdownFieldConfigs; // 返回空列表
        }

        // 2. 从查询结果中收集每个下拉字段的选项值
        boolean updated = false;
        for (DataSourceSearchConfigDTO.DropdownFieldConfig config : dropdownFieldConfigs) {
            String fieldName = config.getName();
            Set<String> options = new LinkedHashSet<>(); // 使用LinkedHashSet保持插入顺序并去重
            
            // 从所有行中收集该字段的值
            for (Map<String, Object> row : rows) {
                if (row.containsKey(fieldName)) {
                    Object value = row.get(fieldName);
                    if (value != null) {
                        options.add(value.toString());
                    }
                }
            }
            
            // 更新配置中的选项列表
            List<String> newOptions = new ArrayList<>(options);
            config.setOptions(newOptions);
            updated = true;
        }

        // 3. 如果有更新，保存到数据源配置中
        if (updated) {
            try {
                String updatedDropdownFields = objectMapper.writeValueAsString(dropdownFieldConfigs);
                dataSource.setDropdownFields(updatedDropdownFields);
                dataSource.setUpdatedAt(LocalDateTime.now());
                dataSourceMapper.updateById(dataSource);
                
                // 将更新信息写入单独的日志文件
                writeDropdownUpdatelog(dataSource.getId(), updatedDropdownFields);
            } catch (Exception e) {
                //log.error("更新数据源ID {} 的下拉字段配置失败: {}", dataSource.getId(), e.getMessage());
            }
        }

        return dropdownFieldConfigs;
    }

    /**
     * 将下拉字段更新信息写入单独的日志文件
     */
    private void writeDropdownUpdatelog(Long dataSourceId, String updatedDropdownFields) {
        try {
            // 创建日志目录（如果不存在）
            Path logDir = Paths.get("logs");
            if (!Files.exists(logDir)) {
                Files.createDirectories(logDir);
            }
            
            // 创建日志文件路径
            Path logFile = logDir.resolve("dropdown_updates.log");
            
            // 写入日志信息
            String logEntry = String.format("[%s] 数据源ID %d 的下拉字段配置更新: %s%n", 
                LocalDateTime.now().toString(), dataSourceId, updatedDropdownFields);
            
            Files.write(logFile, logEntry.getBytes(), 
                java.nio.file.StandardOpenOption.CREATE, 
                java.nio.file.StandardOpenOption.APPEND);
                
        } catch (IOException e) {
            //log.error("写入下拉字段更新日志文件失败: {}", e.getMessage());
        }
    }

    /**
     * 将搜索日志写入单独的日志文件
     */
    private void writeSearchlog(String logFileName, String message) {
        try {
            // 创建日志目录（如果不存在）
            Path logDir = Paths.get("logs");
            if (!Files.exists(logDir)) {
                Files.createDirectories(logDir);
            }
            
            // 创建日志文件路径
            Path logFile = Paths.get(logFileName);
            
            // 写入日志信息
            String logEntry = String.format("[%s] %s%n", 
                LocalDateTime.now().toString(), message);
            
            Files.write(logFile, logEntry.getBytes(), 
                java.nio.file.StandardOpenOption.CREATE, 
                java.nio.file.StandardOpenOption.APPEND);
                
        } catch (IOException e) {
            //log.error("写入搜索日志文件失败: {}", e.getMessage());
        }
    }
}